// Copyright Epic Games, Inc. All Rights Reserved.
 
#pragma once
 
#include "Abilities/LyraGameplayAbility.h"
#include "AbilitySystemComponent.h"
#include "NativeGameplayTags.h"
 
#include "LyraAbilitySystemComponent.generated.h"
 
class AActor;
class UGameplayAbility;
class ULyraAbilityTagRelationshipMapping;
class UObject;
struct FFrame;
struct FGameplayAbilityTargetDataHandle;
 
// 声明游戏标签 TAG_Gameplay_AbilityInputBlocked 的外部定义
LYRAGAME_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_AbilityInputBlocked);
 
/**
 * ULyraAbilitySystemComponent
 *
 *	Base ability system component class used by this project.
 */
UCLASS()
class LYRAGAME_API ULyraAbilitySystemComponent : public UAbilitySystemComponent
{
    GENERATED_BODY()
 
public:
    // 构造函数
    ULyraAbilitySystemComponent(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
 
    //~UActorComponent interface
    // 组件结束播放时的处理
    virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
    //~End of UActorComponent interface
 
    // 初始化能力执行者信息
    virtual void InitAbilityActorInfo(AActor* InOwnerActor, AActor* InAvatarActor) override;
 
    // 定义取消能力的函数类型
    typedef TFunctionRef<bool(const ULyraGameplayAbility* LyraAbility, FGameplayAbilitySpecHandle Handle)> TShouldCancelAbilityFunc;
    // 根据条件函数取消能力
    void CancelAbilitiesByFunc(TShouldCancelAbilityFunc ShouldCancelFunc, bool bReplicateCancelAbility);
 
    // 取消输入激活的能力
    void CancelInputActivatedAbilities(bool bReplicateCancelAbility);
 
    // 输入标签按下处理
    void AbilityInputTagPressed(const FGameplayTag& InputTag);
    // 输入标签释放处理
    void AbilityInputTagReleased(const FGameplayTag& InputTag);
 
    // 处理能力输入
    void ProcessAbilityInput(float DeltaTime, bool bGamePaused);
    // 清空能力输入
    void ClearAbilityInput();
 
    // 检查激活组是否被阻塞
    bool IsActivationGroupBlocked(ELyraAbilityActivationGroup Group) const;
    // 添加能力到激活组
    void AddAbilityToActivationGroup(ELyraAbilityActivationGroup Group, ULyraGameplayAbility* LyraAbility);
    // 从激活组移除能力
    void RemoveAbilityFromActivationGroup(ELyraAbilityActivationGroup Group, ULyraGameplayAbility* LyraAbility);
    // 取消激活组中的能力
    void CancelActivationGroupAbilities(ELyraAbilityActivationGroup Group, ULyraGameplayAbility* IgnoreLyraAbility, bool bReplicateCancelAbility);
 
    // 使用游戏效果添加动态标签
    void AddDynamicTagGameplayEffect(const FGameplayTag& Tag);
    // 移除动态标签的游戏效果
    void RemoveDynamicTagGameplayEffect(const FGameplayTag& Tag);
 
    /** 获取与给定能力句柄和激活信息关联的能力目标数据 */
    void GetAbilityTargetData(const FGameplayAbilitySpecHandle AbilityHandle, FGameplayAbilityActivationInfo ActivationInfo, FGameplayAbilityTargetDataHandle& OutTargetDataHandle);
 
    /** 设置当前的标签关系映射，如果为null则清除 */
    void SetTagRelationshipMapping(ULyraAbilityTagRelationshipMapping* NewMapping);
    
    /** 查看能力标签并收集额外的需求和阻塞标签 */
    void GetAdditionalActivationTagRequirements(const FGameplayTagContainer& AbilityTags, FGameplayTagContainer& OutActivationRequired, FGameplayTagContainer& OutActivationBlocked) const;
 
protected:
    // 尝试在生成时激活能力
    void TryActivateAbilitiesOnSpawn();
 
    // 能力输入按下处理
    virtual void AbilitySpecInputPressed(FGameplayAbilitySpec& Spec) override;
    // 能力输入释放处理
    virtual void AbilitySpecInputReleased(FGameplayAbilitySpec& Spec) override;
 
    // 通知能力激活
    virtual void NotifyAbilityActivated(const FGameplayAbilitySpecHandle Handle, UGameplayAbility* Ability) override;
    // 通知能力激活失败
    virtual void NotifyAbilityFailed(const FGameplayAbilitySpecHandle Handle, UGameplayAbility* Ability, const FGameplayTagContainer& FailureReason) override;
    // 通知能力结束
    virtual void NotifyAbilityEnded(FGameplayAbilitySpecHandle Handle, UGameplayAbility* Ability, bool bWasCancelled) override;
    // 应用能力阻塞和取消标签
    virtual void ApplyAbilityBlockAndCancelTags(const FGameplayTagContainer& AbilityTags, UGameplayAbility* RequestingAbility, bool bEnableBlockTags, const FGameplayTagContainer& BlockTags, bool bExecuteCancelTags, const FGameplayTagContainer& CancelTags) override;
    // 处理能力可取消状态变化
    virtual void HandleChangeAbilityCanBeCanceled(const FGameplayTagContainer& AbilityTags, UGameplayAbility* RequestingAbility, bool bCanBeCanceled) override;
 
    /** 通知客户端能力激活失败 */
    UFUNCTION(Client, Unreliable)
    void ClientNotifyAbilityFailed(const UGameplayAbility* Ability, const FGameplayTagContainer& FailureReason);
 
    // 处理能力失败
    void HandleAbilityFailed(const UGameplayAbility* Ability, const FGameplayTagContainer& FailureReason);
 
protected:
    // 如果设置，此表用于查找激活和取消的标签关系
    UPROPERTY()
    TObjectPtr<ULyraAbilityTagRelationshipMapping> TagRelationshipMapping;
 
    // 这一帧输入被按下的能力句柄
    TArray<FGameplayAbilitySpecHandle> InputPressedSpecHandles;
 
    // 这一帧输入被释放的能力句柄
    TArray<FGameplayAbilitySpecHandle> InputReleasedSpecHandles;
 
    // 输入被保持的能力句柄
    TArray<FGameplayAbilitySpecHandle> InputHeldSpecHandles;
 
    // 每个激活组中运行的能力数量
    int32 ActivationGroupCounts[(uint8)ELyraAbilityActivationGroup::MAX];
};